﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using blackhouse.JavaScript.JQuery;

namespace blackhouse.Web.Controls.Validators {
    public class RegularExpresionValidator : BaseValidator {

        #region Fields

        private WebControl _ctrlToValid;

        #endregion

        #region Properties

        protected WebControl CtrlToValidate {
            get {
                if (this._ctrlToValid == null)
                    this._ctrlToValid = this.FindControl(this.ControlToValidate) as WebControl;
                return this._ctrlToValid;
            }
        }

        [DefaultValue(""), Editor("System.Web.UI.Design.WebControls.RegexTypeEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), Category("Behavior"), Themeable(false)]
        public string ValidationExpression {
            get {
                object obj2 = this.ViewState["ValidationExpression"];
                if (obj2 != null) {
                    return (string)obj2;
                }
                return string.Empty;
            }
            set {
                try {
                    Regex.IsMatch(string.Empty, value);
                }
                catch (Exception exception) {
                    throw new HttpException("Invalid regex", exception);
                }
                this.ViewState["ValidationExpression"] = value;
            }
        }

        [DefaultValue(PredefinedRegexValidators.None), Category("Behavior"), Themeable(false)]
        public PredefinedRegexValidators PredefinedValidator {
            get {
                object obj2 = this.ViewState["PredefinedValidator"];
                if (obj2 != null) {
                    return (PredefinedRegexValidators)obj2;
                }
                return PredefinedRegexValidators.None;
            }
            set {
                this.ViewState["PredefinedValidator"] = value;
            }
        }

        #endregion

        protected override void Render(HtmlTextWriter writer) {
            //base.Render(writer);
        }

        protected override bool EvaluateIsValid() {
            string controlValidationValue = base.GetControlValidationValue(base.ControlToValidate);
            if ((controlValidationValue == null) || (controlValidationValue.Trim().Length == 0)) {
                return true;
            }
            try {
                string validateExpresion = this.ValidationExpression;
                if (this.PredefinedValidator != PredefinedRegexValidators.None)
                    validateExpresion = this.GetPredefinedRegex();
                Match match = Regex.Match(controlValidationValue, validateExpresion, RegexOptions.IgnoreCase);
                return ((match.Success && (match.Index == 0)) && (match.Length == controlValidationValue.Length));
            }
            catch {
                return true;
            }
        }

        private string GetPredefinedRegex() {
            switch (this.PredefinedValidator) {
                case PredefinedRegexValidators.Phone:
                    return @"^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$";
                case PredefinedRegexValidators.Url:
                    return @"^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$";
                case PredefinedRegexValidators.Email:
                    return @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
                case PredefinedRegexValidators.Date:
                    return @"^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$";
                case PredefinedRegexValidators.Number:
                    return @"^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$";
                case PredefinedRegexValidators.Integer:
                    return @"^[\-\+]?\d+$";
                case PredefinedRegexValidators.Ipv4:
                    return @"^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$";
                case PredefinedRegexValidators.OnlyNumberSp:
                    return @"^[0-9\ ]+$";
                case PredefinedRegexValidators.OnlyLetterSp:
                    return @"^[a-zA-Z\ \']+$";
                case PredefinedRegexValidators.OnlyLetterNumber:
                    return @"^[0-9a-zA-Z]+$";
                default:
                    return string.Empty;
            }
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);
            DefineValidator.LoadScript();
            this.CtrlToValidate.PreRender += CtrlToValidate_PreRender;
        }

        void CtrlToValidate_PreRender(object sender, EventArgs e) {
            WebControl ctrl = sender as WebControl;
            DefineValidator dv;
            if (PredefinedValidator == PredefinedRegexValidators.None) {
                dv = new DefineValidator(ctrl, "funcCall[regexValidation]");
                ctrl.Attributes.Add("data-regex", this.ValidationExpression);
            }
            else {
                dv = new DefineValidator(ctrl, "custom[" + this.PredefinedValidator.ToString().ToLower() + "]");
            }
            dv.AddValidator();
            if (!string.IsNullOrEmpty(this.ErrorMessage))
                dv.AddMessage(this.ErrorMessage);
            this.CtrlToValidate.PreRender -= CtrlToValidate_PreRender;
        }

    }
}